package marking.liu.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import marking.liu.constant.StockConstant;
import marking.liu.exception.StockException;
import marking.liu.mapper.StockBlockRtInfoMapper;
import marking.liu.mapper.StockMarketIndexInfoMapper;
import marking.liu.mapper.StockRtInfoMapper;
import marking.liu.pojo.domain.GainerDataDomain;
import marking.liu.pojo.domain.InnerMarketDomain;
import marking.liu.pojo.domain.SectorIndicesDomain;
import marking.liu.pojo.domain.Stock4MinuteDomain;
import marking.liu.pojo.entity.StockRtInfo;
import marking.liu.pojo.vo.PageResult;
import marking.liu.properties.StockInfoProperties;
import marking.liu.service.StockService;
import marking.liu.utils.DateTimeUtil;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

import static marking.liu.utils.DateTimeUtil.getLastDate4Stock;

@Service
@Slf4j
public class StockServiceImpl implements StockService {

    @Autowired
    private StockInfoProperties stockInfoProperties;
    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;
    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;
    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;


    /**
     * 获取国内A股信息
     * @return
     */
    public List<InnerMarketDomain> getInnerMarketInfo() {
//        1、获取股票最新交易时间点 (精确到分钟,秒与毫秒设置为0)
        Date tradeTime = getLastDate4Stock(DateTime.now()).toDate();
        log.info("当前最新的交易时间点为:{}", tradeTime);
//        2、获取大盘编码集合
        List<String> inner = stockInfoProperties.getInner();
//        3、调用mapper查询数据
        List<InnerMarketDomain> marketInfo = stockMarketIndexInfoMapper.getMarketInfo(tradeTime, inner);
//        log.info("查询的值为:{}", marketInfo);
//        4、封装返回结果
        return marketInfo;
    }

    /**
     * 获取板块指数信息
     * @return
     */
    public List<SectorIndicesDomain> getSectorIndicesInfo() {
        SectorIndicesDomain sectorIndicesDomain = SectorIndicesDomain.builder()
                .curDate(getLastDate4Stock(DateTime.now()).toDate())
                .build();
        List<SectorIndicesDomain> sectorIndicesDomainList = stockBlockRtInfoMapper.sectorAllLimit(sectorIndicesDomain);
        log.info("板块指数信息为:{}", sectorIndicesDomainList);
        return sectorIndicesDomainList;
    }

    /**
     * 分页查询最新股票交易时间点下沪深的行情数据
     * @param page
     * @param pageSize
     * @return
     */
    public PageResult getStockPageInfo(Integer page, Integer pageSize) {
//        1、使用pagehelp进行分页查询
        PageHelper.startPage(page, pageSize);
//        2、将最新交易时间点封装到gainerDataDomain中(可能有点多此一举了)
        GainerDataDomain gainerDataDomain = GainerDataDomain.builder()
                .curDate(getLastDate4Stock(DateTime.now()).toDate())
                .build();
//        3、调用mapper查询数据
        List<GainerDataDomain> gainerDataDomainList =  stockRtInfoMapper.getNewestStockInfo(gainerDataDomain);
        log.info("当前分页查询最新股票数据为:{}", gainerDataDomainList);
        Page page1 = (Page) gainerDataDomainList;
        return PageResult.builder()
                .totalRows(Integer.valueOf(page1.getEndRow() - page1.getStartRow()))
                .totalPages(Integer.valueOf(page1.getPages()))
                .pageNum(Integer.valueOf(page1.getPageNum()))
                .pageSize(Integer.valueOf(page1.getPageSize()))
                .size(Integer.valueOf(page1.getPageSize()))
                .rows(gainerDataDomainList)
                .build();
    }

    /**
     * 获取涨幅榜数据
     * @return
     */
    public List<GainerDataDomain> getIncreaseInfo(Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
//        1、获取最新交易时间
        Date date = getLastDate4Stock(DateTime.now()).toDate();
        List<GainerDataDomain> gainerDataDomainList = stockRtInfoMapper.getTop4StockInfo(date);
        Page page1 = (Page) gainerDataDomainList;
        return page1;
    }

    /**
     * 获取涨幅榜统计表数据
     * @return
     */
    public Map<String, List> getStockUpdownCount() {
//        1、获取当日开盘时间点
        Date openTime = DateTimeUtil.getOpenDate(DateTime.now()).toDate();
//        2、获取当前时间点
        Date currTime = getLastDate4Stock(DateTime.now()).toDate();
//        规定flag为涨幅情况 1、涨停 0、跌停
        List<Map> stockUpdownCount = stockRtInfoMapper.getStockUpdownCount(openTime, currTime, 1);
        log.info("涨停的数据为:{}", stockUpdownCount);
        List<Map> stockUpdownCount1 = stockRtInfoMapper.getStockUpdownCount(openTime, currTime, 0);
        log.info("跌停的数据为:{}", stockUpdownCount1);
        Map<String, List> map = new HashMap<>();
        map.put("upList", stockUpdownCount);
        map.put("downList", stockUpdownCount1);
        return map;
    }

    /**
     * 导出涨停跌停excel表
     * @param response
     * @param page
     * @param pageSize
     */
    public void exportExcel(HttpServletResponse response, Integer page, Integer pageSize)  {
//        1.获取最近最新的一次股票有效交易时间点（精确分钟）
        Date curDate = getLastDate4Stock(DateTime.now()).toDate();
//        2.设置分页参数 底层会拦截mybatis发送的sql，并动态追加limit语句实现分页
        PageHelper.startPage(page,pageSize);
        GainerDataDomain gainerDataDomain = GainerDataDomain.builder()
                .curDate(curDate)
                .build();
//        3、调用mapper查询数据
        List<GainerDataDomain> gainerDataDomainList =  stockRtInfoMapper.getNewestStockInfo(gainerDataDomain);
        if (gainerDataDomainList.isEmpty()) {
            throw new StockException(StockConstant.NOTFOUNTINFO);
        }
//        1.设置响应excel文件格式类型
        response.setContentType("*/*");
//        response.setContentType("application/vnd.ms-excel");
//        2.设置响应数据的编码格式
        response.setCharacterEncoding("utf-8");
//        3.设置默认文件名称：兼容一些特殊浏览器
        response.setHeader("content-disposition", "attachment;filename="  + ".xlsx");
//        4.响应easyExcel
        try {
            EasyExcel.write(response.getOutputStream(), GainerDataDomain.class ).sheet("股票信息").doWrite(gainerDataDomainList);
        } catch (IOException e) {
            e.printStackTrace();
            log.info("当前导出数据异常，当前页：{},每页大小：{},异常信息：{}",page,pageSize,e.getMessage());
        }
    }

    /**
     * 统计国内A股大盘T日和T-1日成交量对比功能（成交量为沪市和深市成交量之和）
     * @return
     */
    public Map<String, List> stockTradeVol4InnerMarket() {
//        1、获取T日开盘时间
        DateTime openDate = DateTimeUtil.getOpenDate(getLastDate4Stock(DateTime.now()));
        Date date = openDate.toDate();
//        log.info("T日开盘时间:{}", date);
//        2、获取当前时间
        DateTime currTime = getLastDate4Stock(DateTime.now());
        Date date1 = currTime.toDate();
//        log.info("当前时间:{}", date1);
//        3、获取T-1日开盘时间
        DateTime openDateMin1 = openDate.minusDays(1);
        Date date2 = openDateMin1.toDate();
//        4、获取T-1日收盘时间
        DateTime closeDate = DateTimeUtil.getCloseDate(getLastDate4Stock(DateTime.now().minusDays(1)));
        Date date3 = closeDate.toDate();
//        查询T日数据
        ArrayList<String> markIds = new ArrayList<>();
        Collections.addAll(markIds, "sh000001", "sz399001");
        List<Map> stockTradeVol1 = stockMarketIndexInfoMapper.getStockTradeVol(date, date1, markIds);
        log.info("T日的统计数据:{}", stockTradeVol1);
//        查询T-1日数据
        List<Map> stockTradeVol2 = stockMarketIndexInfoMapper.getStockTradeVol(date2, date3, markIds);
        log.info("T-1日的统计数据:{}", stockTradeVol2);

        Map<String, List> map = new HashMap<>();
        map.put("amtList", stockTradeVol1);
        map.put("yesAmtList", stockTradeVol2);

        return map;
    }

    /**
     * 查询单个个股的分时行情数据，也就是统计指定股票T日每分钟的交易数据；
     *   如果当前日期不在有效时间内，则以最近的一个股票交易时间作为查询时间点
     * @param code
     * @return
     */
    public List<Stock4MinuteDomain> stockScreenTimeSharing(String code) {
//        1、获取当前日期时间
        DateTime now = getLastDate4Stock(DateTime.now());
//        2、获取开盘时间
        DateTime openDate = DateTimeUtil.getOpenDate(DateTime.now());
        List<Stock4MinuteDomain> stock4MinuteDomainList = stockRtInfoMapper.getStockInfoByCodeAndDate(openDate.toDate(), now.toDate(), code);

        return stock4MinuteDomainList;
    }
}
